﻿#ifndef _CMUTEX__H_
#define _CMUTEX__H_

#include "kernel/Referenced.h"

namespace FD
{
	namespace Kernel
	{
		enum MutexType
		{
			Mutex_Normal,
			Mutex_Recursive
		};
		struct FD_MUTEX_DATA;
		class Mutex;
		class MutexInternal
		{
		public:
			MutexInternal(MutexType type = Mutex_Normal);
			~MutexInternal();
			void lock();
			bool tryLock();
			void unlock();
			friend class Mutex;
		private:
			FD_MUTEX_DATA *m_pPrivateData;
		};

		/// <summary>
		/// 互斥体类，提供加锁、解锁、以及尝试加锁的功能
		/// </summary>
		class FD_Kernel_Export Mutex /*: public FD::Kernel::CReferenced*/
		{
		public:
			Mutex();
			Mutex(const Mutex& mutex);
			Mutex& operator=(const Mutex& mutex);

			virtual ~Mutex();

		public:
			/// <summary>
			/// 加锁
			/// </summary>
			/// <param name=""></param>
			/// <returns></returns>
			void lock();
			/// <summary>
			/// 尝试加锁
			/// </summary>
			/// <returns>尝试加锁成功返回true，否则返回false</returns>
			bool tryLock();
			/// <summary>
			/// 解锁
			/// </summary>
			/// <param name=""></param>
			/// <returns></returns>
			void unlock();
		protected:
			Mutex(MutexType type);
		private:
			void *getPrivateData();
			MutexInternal *m_pMutexInternal;
			uint32 m_nOwner;
			uint32 m_nRecursion;
			friend class Condition;
		};
		class FD_Kernel_Export RecursiveMutex : public FD::Kernel::Mutex
		{
		public:
			RecursiveMutex();
			virtual ~RecursiveMutex();
		};

		class FD_Kernel_Export GdalGlobalMutex : public FD::Kernel::RecursiveMutex
		{
		public:
			static GdalGlobalMutex& instance()
			{
				static GdalGlobalMutex pMutex;
				return pMutex;
			};

			GdalGlobalMutex() : RecursiveMutex()
			{};

			virtual ~GdalGlobalMutex()
			{};
		};

		/// <summary>
		/// 自动加锁，解锁类，在构造时通过外部传进来的互斥体指针进行加锁
		///在其析构的时候进行解锁
		/// </summary>
		class FD_Kernel_Export MutexLocker /*: public FD::Kernel::CReferenced*/
		{
		public:
			/// <summary>
			/// 与外部传进来的互斥体指针进行绑定
			/// </summary>
			/// <param name="mutex">外部的互斥体指针</param>
			/// <returns></returns>
			MutexLocker(Mutex *mutex);

		public:
			virtual ~MutexLocker();
		private:
			FD::Kernel::Mutex *m_pMutex;
		};
		struct ConditonData;
		class FD_Kernel_Export Condition /*: public FD::Kernel::CReferenced*/
		{
		public:
			Condition();
			virtual ~Condition();

		public:
			void wait(FD::Kernel::Mutex &mtx,long timeout_ms = INFINITE);
			void notify_one();
			void notify_all();
		private:
			ConditonData *m_pData;
		};

		template <class M> class ScopedLock
		{
		private:
			M& m_lock;
			ScopedLock(const ScopedLock&); // prevent copy
			ScopedLock& operator=(const ScopedLock&); // prevent assign
		public:
			explicit ScopedLock(M& m):m_lock(m) {m_lock.lock();}
			~ScopedLock(){m_lock.unlock();}
		};
	}
}

#endif

